/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_clob_accessor.c                                */
/*  NOTE      =                                                    */
/*  DATE      = 2015/01/14 by songbb                               */
/*******************************************************************/

#include "frcomm.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../ora_mar_engine.h"
#include "../ora_ttc_proto.h"
#include "ora_clob_accessor.h"

/*******************************************************************************
*  FUNC     :  解析 clob 类型数据
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_metadata                       (meta信息)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_clob_accessor_unmarshal_one_row(Conntrack *p_st_conn
                                        , L7session_ora *p_st_sess
                                        , long long ll_options
                                        , L7_ora_packet *p_st_ora_packet
                                        , Sql_metadata_info *p_st_metadata)
{
    short s_tmp = 0;
    int i_tmp = 0;
    long long ll_tmp = 0LL;
    int i_isnull = FR_NO;
    int i_ret = 0;
    int i_isPrefetched;

    if (p_st_metadata->i_isuseless == FR_YES || p_st_metadata->i_isnullbydescribe == FR_YES)
        goto success;

    /**
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/jdbc_oci8/11.2.0.1z/11.2.0.2.0_11.2.0.1_jdbc_oci8_gb2312_all.pcap
     * UP
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [314]
     * tns version? [314]
     * ttc version? [6]
     * version number? [11201]
     * oracle version? [8100]
     * i_ptr_len? [8]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/tmp/13_sqlplus_gb2312_192.168.18.168_10.2.0.1_a_windows_2_192.168.18.241_12.1.0.1_z.pcap
     * UP
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [313]
     * tns version? [313]
     * ttc version? [4]
     * version number? [12101]
     * oracle version? [8100]
     * pro srv version? [6]
     * i_ptr_len? [1]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/2015-03-02/11.2.0.2_11.2.0.3_jdbc_thin_0.pcap
     * UP
     * is use oci? [false]
     * is use special field? [false]
     * tns version send? [310]
     * tns version? [310]
     * ttc version? [6]
     * version number? [11203]
     * oracle version? [8100]
     * pro srv version? [6]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/jdbc_oci8/11.2.0.1a/11.2.0.2.0_11.2.0.1_jdbc_oci8_gb2312_all.pcap
     * UP
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [314]
     * tns version? [314]
     * ttc version? [6]
     * version number? [11201]
     * oracle version? [8100]
     * pro srv version? [6]
     * i_ptr_len? [8]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/tmp/aix_11.2.0.2.0_11.2.0.1_jdbc_oci8_gb2312_all.pcap
     * UP
     * is use oci? [true]
     * is use special field? [false]
     * tns version send? [314]
     * tns version? [314]
     * ttc version? [6]
     * version number? [11201]
     * oracle version? [8100]
     * pro srv version? [6]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/jdbc_oci8/12.1.0.1z/11.2.0.2.0_12.1.0.1_jdbc_oci8_gb2312_all.pcap
     * UP
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [314]
     * tns version? [314]
     * ttc version? [6]
     * version number? [12101]
     * oracle version? [8100]
     * pro srv version? [6]
     * i_ptr_len? [8]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/sqlplus_oci_oracle/10.2.0.4.0_z_gb2312/sqlplus_gb2312_192.168.18.233_10.2.0.4.0_z_2_192.168.18.168_11.2.0.2_a.pcap
     * DOWN
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [313]
     * tns version? [313]
     * ttc version? [4]
     * version number? [11202]
     * oracle version? [8100]
     * i_ptr_len? [8]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/sqlplus_oci_oracle/12.1.0.1_z_gb2312/sqlplus_gb2312_192.168.18.241_12.1.0.1_z_2_192.168.18.239_11.2.0.1_a.pcap
     * DOWN
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [315]
     * tns version? [314]
     * ttc version? [6]
     * version number? [11201]
     * oracle version? [8100]
     * pro srv version? [6]
     * i_ptr_len? [8]
     *
     */

    if ((p_st_sess->i_use_special_field == FR_YES &&
//            ((p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8 && p_st_sess->s_tns_version >= 314)
            ((p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8 && p_st_sess->s_tns_version_req == 314)
//            ((p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8 && p_st_sess->i_oci_stmt_req_skip4_ttc8 == FR_YES)
             || p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_1)) || p_st_sess->i_use_special_field == FR_NO
            )
    {
        ORA_PRINT_INFO("clob_accessor up\n");
        if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC)
            goto error;

        if (ll_tmp == 0LL)
            goto success;

        if (ora_mar_peekUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
            goto error;
        if (ora_mar_escapeSequenceNull(s_tmp, &i_ret) != FR_SUCC)
            goto error;
        if ((i_ret != 1 && s_tmp == 0xfe) || (ll_tmp == s_tmp))
            i_isPrefetched = FR_NO;
        else
            i_isPrefetched = FR_YES;

        ORA_PRINT_DBG("set CLOB i_isPrefetched = %s\n", i_isPrefetched == FR_YES ? "FR_YES" : "FR_NO");

        if (i_isPrefetched == FR_YES)
        {
            if (ora_mar_unmarshalSB8(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // prefetchedLength
                goto error;
            if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // prefetchedChunkSize
                goto error;
            if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // i
                goto error;
            if (s_tmp == 1)
            {
                if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // prefetchedDataCharset
                    goto error;
            }
            if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // prefetchedDataFormOfUse
                goto error;
            if (ora_mar_skipCLR(p_st_sess, p_st_ora_packet) != FR_SUCC) // PrefetchedData
                goto error;
        }

        if (ora_mar_skipCLR(p_st_sess, p_st_ora_packet) != FR_SUCC)
            goto error;
    }
    else
    {
        ORA_PRINT_INFO("clob_accessor down\n");
        // TODO: 此处需要甄别
        /**
        * 1. rm -f core.*;./apm -n -w 10 -d ../oracle/pcap/sqlplus_oci_oracle/10.2.0.4.0_z_gb2312/sqlplus_gb2312_192.168.18.233_10.2.0.4.0_z_2_192.168.18.168_11.2.0.2_a.pcap
        *    [2015/03/16 17:51:14.054586] [2015/03/16 17:51:14.125184] [2015/03/16 17:51:22.566529] [2015/03/16 17:51:22.673915]
        *    860d0000feff0d84000....      220d0000feff0d20000....      00ffff7d05                   fe04273030270000000000
        *
        * 2.
        */

        ORA_PRINT_ALERT("ll_options:[%lld] oacdty:[%d] oacflg:[%d] oacpre:[%d] oacscl:[%d] oacmxl:[%d] oacmal:[%d] oacfl2:[%d] oacvsn:[%d] oaccsi:[%d] oaccsfrm:[%d] oacmxlc:[%d]\n",
                        ll_options,
                        p_st_metadata->s_ora_oacdty,
                        p_st_metadata->s_ora_oacflg,
                        p_st_metadata->s_ora_oacpre,
                        p_st_metadata->s_ora_oacscl,
                        p_st_metadata->i_ora_oacmxl,
                        p_st_metadata->i_ora_oacmal,
                        p_st_metadata->i_ora_oacfl2,
                        p_st_metadata->i_ora_oacvsn,
                        p_st_metadata->i_ora_oaccsi,
                        p_st_metadata->s_ora_oaccsfrm,
                        p_st_metadata->i_ora_oacmxlc);

        if ((ll_options & 0x40000) == 0)
        {
            ORA_PRINT_INFO("oci skip DALC\n");
            if (ora_mar_skipDALC(p_st_sess, p_st_ora_packet) != FR_SUCC)
                goto error;
        }
        else
        {
            ORA_PRINT_INFO("oci skip CLR\n");
            if (ora_mar_skipCLRLen(p_st_sess, p_st_ora_packet, &i_isnull) != FR_SUCC)
                goto error;
            if (i_isnull == FR_YES)
            {
                if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC)
                    goto error;
                if (i_tmp == 0x00)
                {
                    ORA_PRINT_INFO("oci skip 1 bytes\n");
                    if (ora_mar_skip(p_st_ora_packet, 1) != FR_SUCC)
                        goto error;
                }
                else
                {
                    ORA_PRINT_INFO("oci skip 2 bytes\n");
                    if (ora_mar_skip(p_st_ora_packet, 2) != FR_SUCC)
                        goto error;
                }
            }
            else
            {
                ORA_PRINT_INFO("oci skip 4 bytes\n");
                if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                    goto error;
            }
        }
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}
